home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / atan2bug.zip / ATAN2.C < prev    next >
C/C++ Source or Header  |  1990-01-28  |  1KB  |  61 lines

  1. /*
  2.  * This is an unofficial patch for Turbo C's atan2() function.
  3.  *
  4.  * It fixes the erratic behavior of the atan2() function at the
  5.  * coordinate axes.  It's a little cryptic, but should be as fast
  6.  * as the original.  Works with all the memory models, with or
  7.  * without a math coprocessor.
  8.  *
  9.  * Bugs:  Doesn't screen x or y for NaN.  Denormals are not distin-
  10.  *        guished from zero.
  11.  */
  12.  
  13. #include <math.h>
  14. #include <values.h>
  15.  
  16. /*
  17.  * These #defines only work for IEEE 8-byte reals.
  18.  */
  19. #define DOUBLE_EXP_MASK        0x7FF0
  20. #define DOUBLE_SIGN_MASK    0x8000
  21. #define SIGNED(x)     (((short *)(&x))[3] & DOUBLE_SIGN_MASK)
  22. #define EXPONENT(x)    (((short *)(&x))[3] & DOUBLE_EXP_MASK)
  23.  
  24. extern int errno;
  25.  
  26. static const unsigned long QNaN[2] = { 0xFFFFFFFFL, 0x7FFFFFFFL };
  27.  
  28. double atan2(double y, double x)
  29. {
  30.     short exp_x = EXPONENT(x), exp_y = EXPONENT(y);
  31.  
  32.     if (exp_x | exp_y)    /* if x and y are not both zero */
  33.     {
  34.         double z;
  35.         short signed_x;
  36.         short domain = exp_x && (exp_y - exp_x < DMAXPOWTWO << 4);
  37.  
  38.         if (domain)        /* If it's OK to divide y by x */
  39.         {
  40.             z = atan(y/x);
  41.             signed_x = SIGNED(x);
  42.         }
  43.         if (SIGNED(y))    /* Sort out the quadrants... */
  44.         {
  45.             if (domain)
  46.                 return signed_x ? z - M_PI : z;
  47.             else
  48.                 return -M_PI_2;
  49.         }
  50.         else
  51.         {
  52.             if (domain)
  53.                 return signed_x ? z + M_PI : z;
  54.             else
  55.                 return M_PI_2;
  56.         }
  57.     }
  58.     errno = EDOM;
  59.     return *(double *)QNaN;
  60. }
  61.